<template>
  <div class="date-picker-wrapper">
    <div
      class="date-picker-input"
      :class="{ active: visible, range: isRange, disabled }"
      @click="togglePanel"
    >
      <div class="date-display">
        <span v-if="!isRange">{{ displayValue || placeholder }}</span>
        <div v-else class="range-display">
          <span>{{ displayStartDate || startPlaceholder }}</span>
          <span class="separator">至</span>
          <span>{{ displayEndDate || endPlaceholder }}</span>
        </div>
      </div>
      <div class="date-icon iconfont icon-rili"></div>
    </div>

    <transition name="fade">
      <div v-if="visible" class="date-panel" @click.stop>
        <div v-if="!isRange" class="single-date">
          <div class="calendar">
            <div class="header">
              <button @click="prevYear">&lt;&lt;</button>
              <button @click="prevMonth">&lt;</button>
              <span>{{ currentYear }}年{{ currentMonth + 1 }}月</span>
              <button @click="nextMonth">&gt;</button>
              <button @click="nextYear">&gt;&gt;</button>
            </div>
            <div class="weekdays">
              <div v-for="day in weekdays" :key="day">{{ day }}</div>
            </div>
            <div class="days">
              <div
                v-for="date in calendarDays"
                :key="date.key"
                class="day"
                :class="{
                  selected: isSelected(date),
                  today: isToday(date),
                  'other-month': !date.isCurrentMonth,
                }"
                @click="selectDate(date)"
              >
                {{ date.day }}
              </div>
            </div>
          </div>
        </div>

        <div v-else class="range-date">
          <!-- 快捷选择器 -->
          <div class="quick-selectors">
            <div class="quick-buttons">
              <button class="quick-btn" @click="selectQuick('week')">
                近一周
              </button>
              <button class="quick-btn" @click="selectQuick('month')">
                近一个月
              </button>
              <button class="quick-btn" @click="selectQuick('quarter')">
                近三个月
              </button>
            </div>
            <div class="quick-title">快捷选择</div>
            <div class="footer">
              <button class="btn cancel" @click="cancel">取消</button>
              <button class="btn confirm" @click="confirm">确定</button>
            </div>
          </div>

          <div class="calendars">
            <div class="calendar">
              <div class="header">
                <button @click="prevStartYear">&lt;&lt;</button>
                <button @click="prevStartMonth">&lt;</button>
                <span>{{ startYear }}年{{ startMonth + 1 }}月</span>
                <button @click="nextStartMonth">&gt;</button>
                <button @click="nextStartYear">&gt;&gt;</button>
              </div>
              <div class="weekdays">
                <div v-for="day in weekdays" :key="day">{{ day }}</div>
              </div>
              <div class="days">
                <div
                  v-for="date in startCalendarDays"
                  :key="date.key"
                  class="day"
                  :class="{
                    selected: isRangeSelected(date),
                    'in-range': isInRange(date),
                    'range-start': isRangeStart(date),
                    'range-end': isRangeEnd(date),
                    today: isToday(date),
                    'other-month': !date.isCurrentMonth,
                  }"
                  @click="selectRangeDate(date)"
                >
                  {{ date.day }}
                </div>
              </div>
            </div>

            <div class="calendar">
              <div class="header">
                <button @click="prevEndYear">&lt;&lt;</button>
                <button @click="prevEndMonth">&lt;</button>
                <span>{{ endYear }}年{{ endMonth + 1 }}月</span>
                <button @click="nextEndMonth">&gt;</button>
                <button @click="nextEndYear">&gt;&gt;</button>
              </div>
              <div class="weekdays">
                <div v-for="day in weekdays" :key="day">{{ day }}</div>
              </div>
              <div class="days">
                <div
                  v-for="date in endCalendarDays"
                  :key="date.key"
                  class="day"
                  :class="{
                    selected: isRangeSelected(date),
                    'in-range': isInRange(date),
                    'range-start': isRangeStart(date),
                    'range-end': isRangeEnd(date),
                    today: isToday(date),
                    'other-month': !date.isCurrentMonth,
                  }"
                  @click="selectRangeDate(date)"
                >
                  {{ date.day }}
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </transition>

    <div v-if="visible" class="overlay" @click="togglePanel"></div>
  </div>
</template>

<script>
export default {
  name: "DateSelectComponent",
  props: {
    modelValue: { type: [String, Array], default: "" },
    placeholder: { type: String, default: "请选择日期" },
    startPlaceholder: { type: String, default: "开始日期" },
    endPlaceholder: { type: String, default: "结束日期" },
    isRange: { type: Boolean, default: false },
    disabled: { type: Boolean, default: false },
  },
  emits: ["update:modelValue", "change"],
  data () {
    return {
      visible: false,
      currentYear: new Date().getFullYear(),
      currentMonth: new Date().getMonth(),
      startYear: new Date().getFullYear(),
      startMonth: new Date().getMonth(),
      endYear: new Date().getFullYear(),
      endMonth: new Date().getMonth() + 1,
      selectedDate: null,
      selectedStartDate: null,
      selectedEndDate: null,
      weekdays: ["日", "一", "二", "三", "四", "五", "六"],
    };
  },
  computed: {
    displayValue () {
      return this.modelValue || "";
    },
    displayStartDate () {
      return (this.isRange && this.modelValue?.[0]) || "";
    },
    displayEndDate () {
      return (this.isRange && this.modelValue?.[1]) || "";
    },
    calendarDays () {
      return this.generateCalendarDays(this.currentYear, this.currentMonth);
    },
    startCalendarDays () {
      return this.generateCalendarDays(this.startYear, this.startMonth);
    },
    endCalendarDays () {
      return this.generateCalendarDays(this.endYear, this.endMonth);
    },
  },
  watch: {
    modelValue: {
      handler (val) {
        this.initFromValue(val);
      },
      immediate: true,
    },
    startMonth () {
      if (this.startYear === this.endYear && this.startMonth >= this.endMonth) {
        this.endMonth = this.startMonth + 1;
        if (this.endMonth > 11) {
          this.endMonth = 0;
          this.endYear++;
        }
      }
    },
  },
  mounted () {
    if (this.isRange && this.endMonth > 11) {
      this.endMonth = 0;
      this.endYear++;
    }
  },
  methods: {
    togglePanel () {
      if (!this.disabled) this.visible = !this.visible;
    },
    initFromValue (val) {
      if (!val) return;
      if (this.isRange && Array.isArray(val)) {
        if (val[0]) this.selectedStartDate = new Date(val[0]);
        if (val[1]) this.selectedEndDate = new Date(val[1]);
      } else if (!this.isRange && typeof val === "string") {
        this.selectedDate = new Date(val);
        this.currentYear = this.selectedDate.getFullYear();
        this.currentMonth = this.selectedDate.getMonth();
      }
    },
    generateCalendarDays (year, month) {
      const firstDay = new Date(year, month, 1);
      const startDate = new Date(firstDay);
      startDate.setDate(1 - firstDay.getDay());

      const days = [];
      for (let i = 0; i < 42; i++) {
        const date = new Date(startDate);
        date.setDate(startDate.getDate() + i);
        days.push({
          year: date.getFullYear(),
          month: date.getMonth(),
          day: date.getDate(),
          date: new Date(date),
          isCurrentMonth: date.getMonth() === month,
          key: `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`,
        });
      }
      return days;
    },
    prevMonth () {
      this.currentMonth === 0
        ? ((this.currentMonth = 11), this.currentYear--)
        : this.currentMonth--;
    },
    nextMonth () {
      this.currentMonth === 11
        ? ((this.currentMonth = 0), this.currentYear++)
        : this.currentMonth++;
    },
    prevYear () {
      this.currentYear--;
    },
    nextYear () {
      this.currentYear++;
    },
    prevStartMonth () {
      this.startMonth === 0
        ? ((this.startMonth = 11), this.startYear--)
        : this.startMonth--;
    },
    nextStartMonth () {
      this.startMonth === 11
        ? ((this.startMonth = 0), this.startYear++)
        : this.startMonth++;
    },
    prevEndMonth () {
      this.endMonth === 0
        ? ((this.endMonth = 11), this.endYear--)
        : this.endMonth--;
    },
    nextEndMonth () {
      this.endMonth === 11
        ? ((this.endMonth = 0), this.endYear++)
        : this.endMonth++;
    },

    // 年份导航
    prevStartYear () {
      this.startYear--;
    },
    nextStartYear () {
      this.startYear++;
    },
    prevEndYear () {
      this.endYear--;
    },
    nextEndYear () {
      this.endYear++;
    },

    // 快捷选择
    selectQuick (type) {
      const today = new Date();
      let startDate, endDate;

      switch (type) {
      case "week":
        startDate = new Date(today);
        startDate.setDate(today.getDate() - 6);
        endDate = new Date(today);
        break;
      case "month":
        startDate = new Date(today);
        startDate.setMonth(today.getMonth() - 1);
        endDate = new Date(today);
        break;
      case "quarter":
        startDate = new Date(today);
        startDate.setMonth(today.getMonth() - 3);
        endDate = new Date(today);
        break;
      }

      this.selectedStartDate = startDate;
      this.selectedEndDate = endDate;

      // 更新日历显示月份
      this.startYear = startDate.getFullYear();
      this.startMonth = startDate.getMonth();
      this.endYear = endDate.getFullYear();
      this.endMonth = endDate.getMonth();

      // 确保两个月份不同
      if (
        this.startYear === this.endYear &&
        this.startMonth === this.endMonth
      ) {
        this.endMonth = this.startMonth + 1;
        if (this.endMonth > 11) {
          this.endMonth = 0;
          this.endYear++;
        }
      }
    },
    selectDate (dateObj) {
      this.selectedDate = dateObj.date;
    },
    selectRangeDate (dateObj) {
      if (
        !this.selectedStartDate ||
        (this.selectedStartDate && this.selectedEndDate)
      ) {
        this.selectedStartDate = dateObj.date;
        this.selectedEndDate = null;
      } else if (dateObj.date < this.selectedStartDate) {
        this.selectedStartDate = dateObj.date;
        this.selectedEndDate = null;
      } else {
        this.selectedEndDate = dateObj.date;
      }
    },
    isSelected (dateObj) {
      return (
        this.selectedDate && this.isSameDate(dateObj.date, this.selectedDate)
      );
    },
    isRangeSelected (dateObj) {
      return (
        this.selectedStartDate &&
        (this.isSameDate(dateObj.date, this.selectedStartDate) ||
          (this.selectedEndDate &&
            this.isSameDate(dateObj.date, this.selectedEndDate)))
      );
    },
    isRangeStart (dateObj) {
      return (
        this.selectedStartDate &&
        this.isSameDate(dateObj.date, this.selectedStartDate)
      );
    },
    isRangeEnd (dateObj) {
      return (
        this.selectedEndDate &&
        this.isSameDate(dateObj.date, this.selectedEndDate)
      );
    },
    isInRange (dateObj) {
      return (
        this.selectedStartDate &&
        this.selectedEndDate &&
        dateObj.date > this.selectedStartDate &&
        dateObj.date < this.selectedEndDate
      );
    },
    isToday (dateObj) {
      const today = new Date();
      return this.isSameDate(dateObj.date, today);
    },
    isSameDate (date1, date2) {
      return (
        date1.getFullYear() === date2.getFullYear() &&
        date1.getMonth() === date2.getMonth() &&
        date1.getDate() === date2.getDate()
      );
    },
    formatDate (date) {
      return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(
        2,
        "0",
      )}-${String(date.getDate()).padStart(2, "0")}`;
    },
    confirm () {
      let value;
      if (this.isRange) {
        value =
          this.selectedStartDate && this.selectedEndDate
            ? [
              this.formatDate(this.selectedStartDate),
              this.formatDate(this.selectedEndDate),
            ]
            : ["", ""];
      } else {
        value = this.selectedDate ? this.formatDate(this.selectedDate) : "";
      }
      this.$emit("update:modelValue", value);
      this.$emit("change", value);
      this.visible = false;
    },
    cancel () {
      this.initFromValue(this.modelValue);
      this.visible = false;
    },
  },
};
</script>

<style lang="less" scoped>
@primary-color: #4b58dc;

.date-picker-wrapper {
  position: relative;
  display: inline-block;

  .date-picker-input {
    display: flex;
    align-items: center;
    padding: 9px 16px;
    border: 1px solid #dcdfe6;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.3s ease;
    background: #fff;
    min-width: 180px;
    position: relative;
    overflow: hidden;

    &:hover:not(.disabled) {
      border-color: @primary-color;
      box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
      transform: translateY(-2px);

      &:after {
        transform: translateX(120%) skewX(-15deg);
      }
    }

    &:after {
      content: "";
      position: absolute;
      top: 0;
      left: -75%;
      width: 50%;
      height: 100%;
      background: linear-gradient(
        to right,
        rgba(255, 255, 255, 0),
        rgba(255, 255, 255, 0.4),
        rgba(255, 255, 255, 0)
      );
      transform: skewX(-15deg);
      transition: all 0.5s ease;
    }

    &.active {
      border-color: @primary-color;
      background: linear-gradient(
        to right,
        rgba(75, 88, 220, 0.05),
        rgba(75, 88, 220, 0.02)
      );
    }

    &.disabled {
      cursor: not-allowed;
      opacity: 0.6;
      background: #f5f7fa;
    }

    &.range {
      // min-width: 300px;
    }

    .date-display {
      flex: 1;
      color: #606266;
      font-size: 14px;

      .range-display {
        display: flex;
        align-items: center;
        // gap: 8px;
        justify-content: space-between;

        .separator {
          color: #909399;
          font-size: 12px;
        }
      }
    }

    .date-icon {
      margin-left: 8px;
      color: #999;
      font-size: 14px;
    }
  }

  .overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1000;
  }

  .date-panel {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    background: #fff;
    border: 1px solid @primary-color;
    border-radius: 8px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
    z-index: 1001;
    min-width: 100%;

    .single-date {
      padding: 20px;
    }

    .range-date {
      padding: 20px;

      .quick-selectors {
        margin-bottom: 20px;
        padding-bottom: 15px;
        border-bottom: 1px solid #eee;
        display: flex;
        align-items: center;
        justify-content: space-between;
        .quick-title {
          font-size: 14px;
          color: #666;
          font-weight: 500;
        }
        .quick-buttons {
          display: flex;
          gap: 8px;
          .quick-btn {
            padding: 6px 12px;
            border: 1px solid #dcdfe6;
            background: #fff;
            border-radius: 4px;
            cursor: pointer;
            font-size: 12px;
            color: #606266;
            transition: all 0.3s ease;

            &:hover {
              border-color: @primary-color;
              color: @primary-color;
              background: lighten(@primary-color, 48%);
            }

            &:active {
              background: @primary-color;
              color: #fff;
              border-color: @primary-color;
              transform: translateY(1px);
            }
          }
        }
        .footer {
          padding: 12px 20px;
          border-top: 1px solid #eee;
          display: flex;
          justify-content: flex-end;
          gap: 12px;

          .btn {
            padding: 6px 16px;
            border-radius: 4px;
            font-size: 14px;
            cursor: pointer;
            transition: all 0.3s ease;
            border: 1px solid #dcdfe6;

            &.cancel {
              background: #fff;
              color: #606266;

              &:hover {
                border-color: @primary-color;
                color: @primary-color;
              }
            }

            &.confirm {
              background: @primary-color;
              color: #fff;
              border-color: @primary-color;

              &:hover {
                background: lighten(@primary-color, 10%);
                transform: translateY(-1px);
                box-shadow: 0 4px 12px rgba(75, 88, 220, 0.4);
              }
            }
          }
        }
      }

      .calendars {
        display: flex;
        gap: 20px;
      }
    }

    .calendar {
      width: 280px;

      .header {
        display: flex;
        align-items: center;
        justify-content: center;
        margin-bottom: 15px;
        gap: 8px;

        button {
          width: 28px;
          height: 28px;
          border: 1px solid #ddd;
          background: #fff;
          border-radius: 4px;
          cursor: pointer;
          transition: all 0.3s ease;
          font-size: 12px;
          display: flex;
          align-items: center;
          justify-content: center;

          &:hover {
            border-color: @primary-color;
            color: @primary-color;
            background: lighten(@primary-color, 48%);
          }
        }

        span {
          font-size: 14px;
          font-weight: 500;
          color: #333;
          min-width: 120px;
          text-align: center;
        }
      }

      .weekdays {
        display: grid;
        grid-template-columns: repeat(7, 1fr);
        gap: 2px;
        margin-bottom: 8px;

        div {
          text-align: center;
          padding: 8px;
          font-size: 14px;
          color: #666;
          font-weight: 500;
        }
      }

      .days {
        display: grid;
        grid-template-columns: repeat(7, 1fr);
        gap: 2px;

        .day {
          width: 36px;
          height: 36px;
          display: flex;
          align-items: center;
          justify-content: center;
          cursor: pointer;
          font-size: 14px;
          color: #606266;
          transition: all 0.3s ease;
          border-radius: 4px;

          &:hover {
            background: lighten(@primary-color, 40%);
            color: @primary-color;
          }

          &.other-month {
            color: #c0c4cc;
          }

          &.today {
            background: lighten(@primary-color, 45%);
            color: @primary-color;
            font-weight: 600;
          }

          &.selected,
          &.range-start,
          &.range-end {
            background: @primary-color;
            color: #fff;
            font-weight: 500;
          }

          &.in-range {
            background: lighten(@primary-color, 40%);
            color: @primary-color;
          }
        }
      }
    }
  }
}

.fade-enter-active,
.fade-leave-active {
  transition: all 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55);
}

.fade-enter-from {
  opacity: 0;
  transform: translateY(-10px) scale(0.9);
}

.fade-leave-to {
  opacity: 0;
  transform: translateY(-10px) scale(0.9);
}
</style>
